﻿#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
//C语言内存函数
//memcpy函数 mem - memory --内存 cpy - copy - 拷贝
//需要头文件<string.h>
//#include<string.h>
//int main()
//{
//	//strcpy-只针对字符串 完成字符串的拷贝
//	int arr1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
//	//             0  1  2  3  4
//	int arr2[20] = { 0 };
//	//              0  1  2  3  4
//	//memcpy - 针对内存块进行拷贝 不考虑内存块是什么类型
//	//void* memcpy(void* dest, const void* source, size_t num);
//	//函数memcpy从source的位置开始向后复制num个字节的数据到dest指向的内存位置。
//	memcpy(arr2, arr1, 20);//memcpy函数的起始位置和目标位置不能重叠
//	int i = 0;
//	for (i = 0; i < 20; i++)
//	{
//		printf("%d ", arr2[i]);
//	}
//	return 0;
//}

//模拟实现memcpy函数
//memcpy函数拷贝结束后，会返回目标空间的起始地址
#include<assert.h>
////第一种方式
//void* my_memcpy(void* dest,const void* src,size_t num)
//{
//	void* ret = dest;//这样是方便返回目标空间的起始地址
//	assert(dest && src);
//	while (num--)
//	{
//		//使用char*类型的指针进行解引用
//		*(char*)dest = *(char*)src;//既然在这决定进行对指针进行解引用 就最好在前面进行assert断言
//		src = (char*)src + 1;//向后跳动一个字节
//		dest = (char*)dest + 1;
//	}
//	return ret;
//}
//第二种方式
//void* my_memcpy(void* dest,const void* src, size_t num)
//{
//	void* ret = dest;
//	assert(dest && src);
//	while (num--)
//	{
//		*(char*)dest = *(char*)src;
//		((char* )dest)++;
//		((char*)src)++;
//	}
//	return ret;
//}
//int main()
//{
//	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
//	int arr2[20] = { 0 };
//	my_memcpy(arr2, arr1, 20);
//	
//	return 0;
//}

//
//void* my_memcpy(void* dest,const void* src, size_t num)
//{
//	void* ret = dest;
//	assert(dest && src);
//	while (num--)
//	{
//		*(char*)dest = *(char*)src;
//		((char*)dest)++;
//		((char*)src)++;
//	}
//	return ret;
//}
//int main()
//{
//	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
//	//把1 2 3 4 5 拷贝放到3 4 5 6 7的位置上去
//	//             1 2 1 2 3 4 5 8 9 10
//	my_memcpy(arr1+2, arr1, 20);
//	int i = 0;
//	for (i = 0; i < 10; i++)
//	{
//		//自己写的这个函数只是能够完成不重叠内存块的拷贝
//		// 在复制完 1 2 放到3 4的位置之后 这个3的位置已经是1 5的位置是要放新的数据
//		// 但是这时候变成了1 所以就出现了错误
//		printf("%d ", arr1[i]);//结果是 1 2 1 2 1 2 1 8 9 10
//		//memcpy函数是不考虑内存重叠的情况 虽然能完成这个操作 结果变成1 2 1 2 3 4 5 8 9 10 
//		// 但是复制的结果都是未定义的
//	}
//
//	return 0;
//}

//那么重叠的内存块拷贝谁去做呢？
//memmove函数来实现
//和memcpy的差别就是memmove函数处理的源内存块和⽬标内存块是可以重叠的
//void* memmove(void* dest,const void* src,size_t num)
//int main()
//{
//	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
//	memove(arr + 2, arr, 5 * sizeof(int));
//	int i = 0;
//	for (i = 0; i < 10; i++)
//	{
//		printf("%d ", arr[i]);
//	}
//	return 0;
//}

////模拟实现memmove函数
////memmove函数拷贝完成后，会返回目标空间的起始地址
//void* my_memmove(void* dest,const void* src,size_t num)
//{
//	//只要是有重叠的情况 当dest落在了src前面的时候 就从前向后拷贝
//	//只要是有重叠的情况 dest落在了src后面的时候 就从后往前拷贝
//	//在不重叠的情况下 从前向后还是从后向前拷贝都是可以的
//
//	//所以可以划分为两种方式
//	//1.前->后 后->前 后->前
//	//2.前->后 后->前 前->后
//	assert(dest && src);
//	void* ret = dest;
//	if (dest < src)
//	{
//		//前->后
//		while (num--)
//		{
//			*(char*)dest = *(char*)src;
//			dest = (char*)dest + 1;
//			src = (char*)src + 1;
//		}
//	}
//	else
//	{
//		//后->前
//		while (num--)//num在这等于20 while循环为真 进入循环这时候num就变成了19
//		{
//			*((char*)dest+num) = *((char*)src + num);//num等于19 加上19就得到了最后的一个字节的地址 
//			//再进行解引用操作 在这src和dest相当于没动  因为当num执行--操作的时候 这里的src会变化 dest也会变化
//		}
//	}
//	return ret;
//}
//int main()
//{
//	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
//	my_memmove(arr + 2, arr, 5 * sizeof(int));
//	int i = 0;
//	for (i = 0; i < 10; i++)
//	{
//		printf("%d ", arr[i]);
//	}
//	return 0;
//}

int main()
{

	return 0;
}